#include <QtCore/QCoreApplication>


#include <QPluginLoader>
#include <QDir>
#include <QTextStream>
#include <QFile>

#include "fileLoader.h"

#include <iostream>

using namespace PBVP;
using namespace std;

//constructor
FileLoader:: FileLoader(int argc, char *argv[])
{
	loadPlugin(argc, argv);
	file = new QFile("Data.txt");
}

//load the saved rawiv or raw file
void FileLoader::loadRawivFile(QString srchStr, QString type, std::vector<Reg3DVolumeData *> &volumeDataVector )
{
	//std::cout <<"************************************************"<<std::endl;
	QDir fileDir = QDir(dir);
	//QDir fileDir = QDir("C:/Users/joshi001/Thesis/TestData");	//std::cout << fileDir.absolutePath().toStdString() << std::endl;
	if (fileDir.dirName().toLower() == "debug" 
		|| fileDir.dirName().toLower() == "release") 
	{
			fileDir.cdUp();
	}

	std::cout << fileDir.absolutePath().toStdString() << std::endl;
	fileDir.cdUp();
	std::cout << fileDir.absolutePath().toStdString() << std::endl;
	
	QStringList filters;
	filters << type;
	fileDir.setNameFilters(filters); 
	QStringList fileEntries = fileDir.entryList(QDir::Files);
	/*foreach (QString fileName, fileEntries)
	{
		//std::cout << fileName.toStdString() << std::endl;
		if (fileName.contains(srchStr))
		{
			
			std::cout<<"Loading "<<fileName.toStdString()<<std::endl;
			//volumeDataVector.push_back(dynamic_cast<Reg3DVolumeData *>(rawivPlugin->loadFile(fileName)));

		} 
	}*/
	
	QStringList tmpFname,tmpFname1;
	QString fName;
	int count=0;

	std::vector<QString> fileVector;
	for(int i=0; i<fileEntries.size() ; i++)
	{
		QString fileName;
		fileName = fileEntries.at(i);
		if (fileName.contains(srchStr))
		{
			fileVector.push_back(fileName);
		} 
	}
	//This is required to load the ligands in the order in which they were created previously
	if(srchStr.contains("Lig"))
	{
		while(!fileVector.empty())
		{
			//std::iterator itr = fileVector.begin(); 
			std::vector<QString>::iterator itr;
			fName = fileVector.front();
			itr=fileVector.begin();
			tmpFname = fName.split("_");
			tmpFname1 = tmpFname.at(1).split(".");
			//cout<<tmpFname1.at(0).toStdString()<<endl;
			if(tmpFname1.at(0).trimmed().toInt() == count)
			{
				std::cout<<"Loading "<<fName.toStdString()<<std::endl;
				volumeDataVector.push_back(dynamic_cast<Reg3DVolumeData *>(rawivPlugin->loadFile(fName)));
				fileVector.erase(itr);
				itr=fileVector.begin();
				count++;
			}
			else//move front to back
			{
				fileVector.erase(itr);
				itr = fileVector.end();
				fileVector.insert(itr,fName);
			}
			tmpFname.empty();
			tmpFname1.empty();
		}
	}
	else
		for (int i =0; i< fileVector.size(); i++)
		{
			fName = fileVector.at(i);
			std::cout<<"Loading "<<fName.toStdString()<<std::endl;
			volumeDataVector.push_back(dynamic_cast<Reg3DVolumeData *>(rawivPlugin->loadFile(fName)));
		}

		while(!fileVector.empty())
		{
			fileVector.pop_back();
		}
}

//creates a pdbList.txt file with a list of pdb filename in the folder
//First entry in the file is the number of pdb filename
QStringList FileLoader::getPdbFileList(void)
{
	//std::cout <<"************************************************"<<std::endl;
	QDir fileDir = QDir(dir);
	//std::cout << fileDir.absolutePath().toStdString() << std::endl;
	if (fileDir.dirName().toLower() == "debug" 
		|| fileDir.dirName().toLower() == "release") 
	{
			fileDir.cdUp();
	}

	//std::cout << fileDir.absolutePath().toStdString() << std::endl;
	fileDir.cdUp();
	//std::cout << fileDir.absolutePath().toStdString() << std::endl;
	fileDir.cd("TestData");
	QStringList filters;
	filters << "*.pdb";
	fileDir.setNameFilters(filters); 
	QStringList fileEntries = fileDir.entryList(QDir::Files);
	
	
	/*file = new QFile("pdbList.txt");
	QTextStream out(file);
	file->open(QIODevice::WriteOnly | QIODevice::Text);
	out<<fileEntries.count()<<endl;
	foreach (QString fileName, fileEntries)
	{
		out<<fileName<<endl;
	}
	file->close();
	*/
	return fileEntries;
}



//create filename
QString FileLoader::getFName(QString pdbName, QString id, int index, QString ext)
{
	QString ind, name;
	if(index == -1)
		name = pdbName + id + ext;
	else
	{
		ind.setNum(index);
		name = pdbName + id + ind + ext;
	}
	return name;
}


void FileLoader::loadPlugin(int argc, char *argv[])
{
	// load plugins
	QCoreApplication a(argc, argv);
	dir = a.applicationDirPath();

	QDir pluginsDir = QDir(a.applicationDirPath());
	//std::cout << pluginsDir.absolutePath().toStdString() << std::endl;
	if (pluginsDir.dirName().toLower() == "debug" 
		|| pluginsDir.dirName().toLower() == "release") {
			pluginsDir.cdUp();
	}

	//std::cout << pluginsDir.absolutePath().toStdString() << std::endl;
	pluginsDir.cdUp();
	//std::cout << pluginsDir.absolutePath().toStdString() << std::endl;
	pluginsDir.cd("plugins");
	//std::cout << pluginsDir.absolutePath().toStdString() << std::endl;

	QStringList pluginEntries = pluginsDir.entryList(QDir::Files);

	// check additional potential plugin path if necessary
	if(pluginEntries.size() == 0) {
		pluginsDir = QDir(a.applicationDirPath());
		pluginsDir.cd("plugins");
		pluginEntries = pluginsDir.entryList(QDir::Files);
	}

	foreach (QString fileName, pluginEntries) {
		//std::cout << fileName.toStdString() << std::endl;
		if (fileName.contains("rawiv"))
		{
			QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
			QObject *plugin = loader.instance();
			if (plugin) {
				rawivPlugin = qobject_cast<FilePluginInterface *>(plugin);
				if (rawivPlugin) {
					rawivPlugin->initialize(NULL);
					//std::cout << rawivPlugin->description().toStdString() << std::endl;		
				} 
			}
		} 
		else
		if (fileName.contains("rawfile"))
		{
			QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
			QObject *plugin = loader.instance();
			if (plugin) {
				rawPlugin = qobject_cast<FilePluginInterface *>(plugin);
				if (rawPlugin) {
					rawPlugin->initialize(NULL);
					//std::cout << rawPlugin->description().toStdString() << std::endl;		
				} 
			}
		} else if (fileName.contains("pdb"))
		{
			QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
			QObject *plugin = loader.instance();
			if (plugin)
			{
				pdbPlugin = qobject_cast<FilePluginInterface *>(plugin);
				if (pdbPlugin) 
				{
					pdbPlugin->initialize(NULL);
					//std::cout << pdbPlugin->description().toStdString() << std::endl;
				}
			}
		}
		else if (fileName.contains("rawncfile"))
		{
			QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
			QObject *plugin = loader.instance();
			if (plugin)
			{
				rawncPlugin = qobject_cast<FilePluginInterface *>(plugin);
				if (rawncPlugin) 
				{
					rawncPlugin->initialize(NULL);
					std::cout << rawncPlugin->description().toStdString() << std::endl;
				}
			}
		}
	}
}
void FileLoader::setFileName(QString pdbName)
{
	QString vFile;
	vFile = pdbName + "Vol.txt";
	file = new QFile(vFile);
}


void FileLoader::write(QString str, double vol)
{
	QTextStream out(file);
	file->open(QIODevice::Append | QIODevice::Text);
	out<<str<<vol<<endl;
}

void FileLoader::write(QString str, QString value)
{
	QTextStream out(file);
	file->open(QIODevice::Append | QIODevice::Text);
	out<<str<<value<<endl;
}

		